package site.immonkey.mymvc.bean;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import site.immonkey.mymvc.annotation.ExcludeInterceptorAnnotation;
import site.immonkey.mymvc.annotation.InterceptorAnnotation;
import site.immonkey.mymvc.filter.MvcFilter;
import site.immonkey.mymvc.interceptor.Interceptor;

public class RequestMapper {
    private String requestPath;
    private Method method;
    private Class<?> handleClass;
    private List<Class<? extends Interceptor>> _interceptors;

    public String getRequestPath() {
        return requestPath;
    }

    public void setRequestPath(String requestPath) {
        this.requestPath = requestPath;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public Class<?> getHandleClass() {
        return handleClass;
    }

    public void setHandleClass(Class<?> handleClass) {
        this.handleClass = handleClass;
    }

    public Iterator<Class<? extends Interceptor>> getInterceptorIterator() {
        return new InterceptorClass();
    }
    
    private class InterceptorClass implements Iterator<Class<? extends Interceptor>> {
        private List<Class<? extends Interceptor>> interceptors;
        private Iterator<Class<? extends Interceptor>> iterator;

        public InterceptorClass() {
            if(_interceptors == null) {
                synchronized (requestPath) {
                    if(_interceptors == null) {
                        InterceptorAnnotation methodInterceptorAnnotation = method.getAnnotation(InterceptorAnnotation.class);
                        ExcludeInterceptorAnnotation methodExcludeInterceptorAnnotation = method.getAnnotation(ExcludeInterceptorAnnotation.class);
                        InterceptorAnnotation controllerInterceptorAnnotation = handleClass.getAnnotation(InterceptorAnnotation.class);
                        ExcludeInterceptorAnnotation controllerExcludeInterceptorAnnotation = handleClass.getAnnotation(ExcludeInterceptorAnnotation.class);
                        
                        _interceptors = new ArrayList<Class<? extends Interceptor>>(MvcFilter.getGlobalInterceptors());
                        if(controllerInterceptorAnnotation != null) {
                            _interceptors.addAll(Arrays.asList(controllerInterceptorAnnotation.value()));
                        }
                        if(methodExcludeInterceptorAnnotation != null) {
                            _interceptors.removeAll(Arrays.asList(methodExcludeInterceptorAnnotation.value()));
                        }
                        
                        if(methodInterceptorAnnotation != null) {
                            _interceptors.addAll(Arrays.asList(methodInterceptorAnnotation.value()));
                        }
                        
                        if(controllerExcludeInterceptorAnnotation != null) {
                            _interceptors.removeAll(Arrays.asList(controllerExcludeInterceptorAnnotation.value()));
                        }
                    }
                }
            }
            interceptors = new ArrayList<Class<? extends Interceptor>>(_interceptors);
            iterator = interceptors.iterator();
        }
        
        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }

        @Override
        public Class<? extends Interceptor> next() {
            return iterator.next();
        }

        @Override
        public void remove() {
            throw new RuntimeException();
        }
    }
}
